s3fsを使ってEC2からS3をマウントしたときにうまくいかなくて調べた事まとめ
こんにちは植木和樹です。今回はタイトル通りs3fsという仕組みを使ってEC2からS3をマウントしてみました。
解決したい問題
たとえば複数のWebサーバがあった時に、サーバ間でファイルを共有したいってことがあります。Webアプリの処理でファイルを作る場合、あるEC2インスタンス障害が発生してダウンしても別のインスタンスからアクセスできるようにしておきたい、といったケースです。
解決策として以下の案が思いつきます。
- NFSで領域を共有する
- RDSにファイルを格納する
- S3にファイルをアップロードする
既存のアプリをなるべく変更せずに対応するとなるとNFSサーバを用意するのが手っ取り早いのですが、そうなるとNFSサーバが単一障害点(SPOF)になります。冗長かのためにEC2インスタンスの数が増えて構成が複雑になるのはなるべく避けたいですよね。
ということで信頼性の高いS3ストレージをなんとかお手軽に扱えないか、というのが今回の取り組みです。
s3fsとは
s3fsというのは、その名前の通りS3のバケットをファイルシステムとしてマウントできる仕組みです。FUSE(Filesystem in Userspace)という一般ユーザが様々なファイルシステムを作成できる機能を用いて実装されています。 *1
IAMユーザの作成
S3バケットへのアクセスは権限を持ったIAMユーザ(アクセスキーとシークレットアクセスキー)で行います。IAM Roleには対応していないようです(v1.70)。
マネージメントコンソールのIAMの画面からS3アクセス用のユーザを作り、アクセスキーとシークレットアクセスキーを入手しておいてください。
インストールと設定
EC2インスタンスのOSは Amazon Linux AMI 2013.03.1(x86_64)を使用しました。
s3fsはyumパッケージで提供されていないのでソースからコンパイルします。コンパイルに必要なパッケージをインストールしたら、configure、make、make installでOKです。
$ sudo yum -y update $ sudo yum -y install gcc-c++ fuse fuse-devel libcurl-devel libxml2-devel openssl-devel $ curl -O http://s3fs.googlecode.com/files/s3fs-1.70.tar.gz $ tar xzf s3fs-1.70.tar.gz $ cd s3fs-1.70 $ ./configure --prefix=/usr/local $ make $ sudo make install $ find /usr/local -type f /usr/local/bin/s3fs /usr/local/share/man/man1/s3fs.1
アクセスキーとシークレットアクセスキーを設定します。キーを設定する方法は4つあります。
- コマンドラインオプションpasswd_fileを指定する
- 環境変数 AWSACCESSKEYID、 AWSSECRETACCESSKEY を指定する
- マウントを実行するユーザのホームディレクトリに.passwd-s3fsというパスワードファイルを作成する
- /etc/passwd-s3fs にパスワードファイルを作成する
今回は /etc/passwd-s3fs にファイルを作成します。ファイルは2種類の記述方法があるのですが、今回はS3のバケットによってアクセスキーを変えることができるよう「バケット名」「アクセスキー」「シークレットアクセスキー」をコロンで区切った文字列を書いておきます。
$ echo "bucketname:access_key:secret_access_key" | sudo tee -a /etc/passwd-s3fs $ sudo chmod 640 /etc/passwd-s3fs
s3fs 1.63以降の注意点
s3fsはv1.63以降パーミッションの取り扱いが変わっています。このためマウントオプションを指定しないと「ファイル一覧は表示できるけど、一般ユーザでファイルの中身を見ようとするとPermission Deniedされる」という問題がでます。補足するとS3のバケットにマネージメントコンソールからアップロードしたファイルでこの問題がでます。
$ ls -l /share/s3fs_test.txt ---------- 1 root root 6 6月 2 01:54 2013 /share/s3fs_test.txt $ cat /share/s3fs_test.txt cat: /share/s3fs_test.txt: 許可がありません
詳細な経緯は Issue 321に書かれています。v1.62まではファイルへのアクセスをすべてroot権限で行っていたので読み書きできていたのが、v1.63以降user/group/modeを考慮するようになったためだそうです。ファイルの権限はS3のファイル個々に設定されたメタデータx-amz-meta-modeから判断するのですが、マネージメントコンソールからアップロードされたファイルにはこのメタデータが付与されないため上述の問題が発生します。
これを解決するにはv1.69(2013/5/16リリース)で追加されたuid/gidマウントオプションを使います。このオプションによりメタデータが設定されていないファイルについては、指定したuid/gidがオーナー(グループ)として扱われるので読み書きできるようになります。
マウント、読み書き、アンマウント、fstab
マウント
一般ユーザ(今回はec2-user)から読み書きできるよう設定します。idコマンドによるとec2-userのuidは222、gidは500です。
$ id ec2-user uid=222(ec2-user) gid=500(ec2-user) 所属グループ=500(ec2-user),10(wheel) $ sudo mkdir /share $ ls -ld /share drwxr-xr-x 2 root root 4096 6月 2 01:52 2013 /share $ sudo /usr/local/bin/s3fs bucketname /share -o rw,allow_other,use_cache=/tmp,uid=222,gid=500 $ ls -ld /share drwxr-xr-x 1 ec2-user ec2-user 0 1月 1 00:00 1970 /share
読み書き
ファイルを読み書きしてみます。マネージメントコンソールからアップロードしたs3fs_test.txtのパーミッションは000ですが、uidオプションによってオーナーがec2-userになっているため読み書きすることができます。
$ ls -l /share/s3fs_test.txt ---------- 1 ec2-user ec2-user 6 6月 2 01:54 2013 /share/s3fs_test.txt $ cat /share/s3fs_test.txt Hello $ echo "Hello" >> /share/s3fs_test.txt $ cat /share/s3fs_test.txt Hello Hello $ echo "World" > /share/s3fs_test2.txt $ ls -l /share/s3fs_test2.txt -rw-rw-r-- 1 ec2-user ec2-user 6 6月 2 02:12 2013 /share/s3fs_test2.txt $ cat /share/s3fs_test2.txt World
なおs3fsで作成したファイルには上述のメタデータが付与されます。
アンマウント
アンマウントはfusermountコマンドを実行します。
$ sudo fusermount -u /share
/etc/fstab
OS起動時にS3をマウントする場合は/etc/fstabにエントリを追加します。
s3fs#bucketname /share fuse auto,rw,allow_other,use_cache=/tmp,uid=222,gid=500 0 0
読み書きにあたっての注意点
書き込みレスポンス速度
「遅い!!」この一言に尽きます。echoコマンドで"World"という文字列をファイルに書き出すだけで1〜2秒くらいかかります。これはS3とのやりとりをHTTPのリクエスト/レスポンスで行っているためです。ローカルストレージのブロックデバイスではないので仕方がないですね。Webアプリから直接このS3領域に書き込むのではなく一旦ローカルディスクに書き込み、rsyncなどで定期的に同期してあげると良いでしょう。
読み込みキャッシュの問題
マウントオプションでuse_cache=/tmpのようにキャッシュディレクトリを指定すると、読み書きしたファイルを/tmp/<bucketname>にキャッシュしてくれるので2回目以降の読み込みが高速になります。
ところが弊害もあり別EC2インスタンスからファイルが更新されても、それを知らずにキャッシュをみてしまいます。あるファイルへの書き込みが特定のEC2インスタンスからのみの場合は問題になりませんが、複数インスタンスから更新処理が重なった場合には不整合がおきますので注意してください。
結論
S3をファイルシステムとしてマウントすることができました。lsやcp、cat、rsyncなど扱い慣れたコマンドでファイルを操作できるのは便利です。ただ、ややレスポンス速度の面などで使いどころは考慮する必要があります。
使い方によってはNFSサーバが不要になり、システム構成をシンプルにする(=コストダウンする)ことができるため、同様の問題で困っている方は検討されてはいかがでしょうか。
脚注
- http://ja.wikipedia.org/wiki/Filesystem_in_Userspace ↩